package server.resolver.resource;


import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultFileRegion;
import io.netty.handler.codec.http.*;
import server.response.HttpResponse;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @author cg
 * @date 2023/6/7 14:12
 */
public class DefaultResourceResolver implements ResourceResolver {
    //单例模式
    private volatile static DefaultResourceResolver instance;

    private void HtmlResolver() {
    }

    public static DefaultResourceResolver getInstance() {
        if (instance == null) {
            synchronized (DefaultResourceResolver.class) {
                if (instance == null) {
                    instance = new DefaultResourceResolver();
                }
            }
        }
        return instance;
    }

    /**
     * 读取文件并响应给前端
     * @param file 文件名
     * @param httpResponse 请求响应
     * @param contentType 响应类型
     * @throws IOException
     */
    @Override
    public void resolve(File file, HttpResponse httpResponse, String contentType) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(file, "r");
        long fileLength = raf.length();
        //设置默认响应头
        ChannelHandlerContext ctx = httpResponse.getCtx();
        DefaultHttpResponse defaultHttpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        //设置响应类型
        defaultHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
        //设置响应长度
        defaultHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, fileLength);
        //写入请求头
        ctx.write(defaultHttpResponse);
        //写入文件数据
        ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
        //写入结尾符号
        ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
        //响应结束后关闭通道
        lastContentFuture.addListener(ChannelFutureListener.CLOSE);
    }
}
